#include <cassert>
#include <iostream>
#include <cstdlib>
#include <omp.h>
#include <cmath>
#include <cublas_v2.h>
#include <cusparse.h>
#include <tuple>

#include "cuda/cuda_utils.cuh"

#include "dense.cuh"

template <class SubCls>
struct Benchmarker {
  Benchmarker()
  {
    H_ERR(cudaEventCreate(&timerStart_));
    H_ERR(cudaEventCreate(&timerStop_));
  }

  ~Benchmarker()
  {
    H_ERR(cudaEventDestroy(timerStart_));
    H_ERR(cudaEventDestroy(timerStop_));
  } 

  inline float run(int iterations, int data_copies) { return SubCls::run(iterations, data_copies); }

protected:
  cudaEvent_t timerStart_, timerStop_;
  inline void start() { H_ERR(cudaEventRecord(timerStart_)); }
  inline void stop() { H_ERR(cudaEventRecord(timerStop_)); }
  inline float time_elapse_total() 
  {
    float ret;
    H_ERR(cudaEventElapsedTime(&ret, start, end));
    return ret;
  }
};

struct ReducetionBenchmark: public Benchmarker<ReducetionBenchmark>
{
  using Benchmarker<ReducetionBenchmark>::start;
  using Benchmarker<ReducetionBenchmark>::stop;
  using Benchmarker<ReducetionBenchmark>::time_elapse_total;

};
